package com.ddwl.goods.service;

import com.ddwl.common.constant.BaseEnum;
import com.ddwl.common.constant.GoodsEnum;
import com.ddwl.schema.bo.goods.*;
import com.ddwl.schema.vo.goods.LimitTimeGoAndTimeVo;
import org.springframework.util.CollectionUtils;
import com.ddwl.common.exception.ParamException;
import com.ddwl.common.feign.api.ShopApi;
import com.ddwl.schema.bo.order.ChangeStockBo;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.goods.dao.ItemDao;
import com.ddwl.goods.dao.ItemTagDao;
import com.ddwl.goods.dao.LimitTimePurActiveDao;
import com.ddwl.goods.dao.LimitTimePurGoodDao;
import com.ddwl.goods.dao.model.LimitTimePurActive;
import com.ddwl.goods.dao.model.LimitTimePurGood;
import com.ddwl.goods.model.ItemTag;
import com.ddwl.schema.bo.order.SkuSaleBo;
import com.ddwl.schema.vo.goods.LimitTimePurActiveVo;
import com.ddwl.schema.vo.goods.LimitTimePurGoodVo;
import com.ddwl.schema.vo.goods.LimitTimePurItemVo;
import com.ddwl.schema.vo.order.OrderSpuVo;
import com.ddwl.schema.vo.shop.ShopVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.util.StringUtil;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 秒杀service
 * @author wenbin
 */
@Service
@RefreshScope
@Slf4j
public class LimitTimePurActiveService {

    @Resource
    private ShopApi shopApi;
    @Resource
    private LimitTimePurActiveDao limitTimePurActiveDao;
    @Resource
    private LimitTimePurGoodDao limitTimePurGoodDao;
    @Resource
    private ItemDao itemDao;
    @Resource
    private ItemTagDao itemTagDao;

    private String checkValue(LimitTimePurActiveBo bo, String userId) {
        ParamException.isNull(bo.getEndTime(),"结束时间不能为空");
        ParamException.isNull(bo.getStartTime(),"起始时间不能为空");
        ParamException.isNull(bo.getLimitTimePurGoodVo(),"活动商品不能为空");
        ParamException.isBlank(bo.getShopId(),"店铺id不能为空");
        ParamException.isTrue(bo.getStartTime()!=null&&bo.getEndTime()!=null&&bo.getStartTime().compareTo(bo.getEndTime())>=0,"开始时间不能大于结束时间");
        ShopVo shopVo = shopApi.judgeUserHasShop(userId,bo.getShopId()).getResult();
        ParamException.isNull(shopVo,"当前用户没有权限进行限时购操作");
        QueryLimitTimePurActiveBo query=new QueryLimitTimePurActiveBo();
        query.setShopId(shopVo.getId());
        query.setIsEffect(1);
        if (StringUtil.isNotEmpty(bo.getId())){
            query.setId(bo.getId());
        }
        List<LimitTimePurActive> limitTimePurActiveVoList = limitTimePurActiveDao.queryLimitTimePurActive(query);
        if (limitTimePurActiveVoList!=null&&limitTimePurActiveVoList.size()!=0){
            List<LimitTimePurActive> list = limitTimePurActiveVoList.stream().filter(o -> bo.getStartTime().compareTo(o.getStartTime()) > 0
                    && bo.getStartTime().compareTo(o.getEndTime()) < 0 || bo.getEndTime().compareTo(o.getStartTime()) > 0
                    && bo.getStartTime().compareTo(o.getEndTime()) < 0).collect(Collectors.toList());
            ParamException.isTrue(list!=null&&list.size()!=0,"活动时间不能重叠");
        }
        //校验商品是否有重复
        List<String> groupList = new ArrayList<>(4);
        bo.getLimitTimePurGoodVo().stream().forEach(e -> {
            if (StringUtils.hasText(e.getItemId())) {
                groupList.add(e.getItemId());
            }
        });
        ParamException.isTrue(groupList.stream().distinct().collect(Collectors.toList()).size()>4,"最多添加4个商品");
        return shopVo.getId();
    }

    /**
     * 新建活动
     * */
    @Transactional(rollbackFor = Throwable.class)
    public void create(LimitTimePurActiveBo bo, String userId) {
        ParamException.isFalse(!StringUtils.hasText(bo.getId()));
        checkValue(bo, userId);
        //bo.setShopId(shopId);
        bo.setIsEffect(1);
        LimitTimePurActive limitTimePurActive = BeanConverUtils.convertBean(bo, LimitTimePurActive.class, "id");
        limitTimePurActiveDao.insert(limitTimePurActive);
        createLimitGoods(bo.getLimitTimePurGoodVo(), limitTimePurActive);
    }


    private void createLimitGoods(List<LimitTimePurGoodBo> limitTimePurGoodBo,LimitTimePurActive insert) {

        //校验商品是否有重复
        List<String> groupList = new ArrayList<>(4);
        limitTimePurGoodBo.stream().forEach(e -> {
            if (StringUtils.hasText(e.getBarcode())) {
                groupList.add(e.getBarcode());
            }
        });
        int distinctGroupSize = groupList.stream().distinct().collect(Collectors.toList()).size();
        ParamException.isTrue(groupList.size() > distinctGroupSize,"商品有重复");
        for (LimitTimePurGoodBo bo:limitTimePurGoodBo) {
            ParamException.isBlank(bo.getItemId(),"商品id为空");
            ParamException.isNull(bo.getLimitPrice(),"商品价格");
            ParamException.isNull(bo.getLimitCount(),"限购数量为空");
            ParamException.isNull(bo.getBarcode(),"商品编码为空");
            bo.setShopId(insert.getShopId());
            bo.setLimitActiveId(insert.getId());
            if (bo.getDistAmount()==null){
                bo.setDistAmount(BigDecimal.ZERO);
            }
            LimitTimePurGood limitTimePurGood = BeanConverUtils.convertBean(bo, LimitTimePurGood.class);
            limitTimePurGood.setIsEffect(1);
            limitTimePurGood.setViewCount(0);
            limitTimePurGood.setSaleCount(0);
            limitTimePurGood.setSales(0);
            limitTimePurGood.setIsEffect(1);
            limitTimePurGood.setOldSaleCount(0);
            limitTimePurGoodDao.insert(limitTimePurGood);
            //更新标签
        }
        String repeat = limitTimePurGoodDao.checkItemRepeat();
        ParamException.isTrue(StringUtil.isNotEmpty(repeat),"商品重复上架活动:"+repeat);
        batchUpdateItemSign(limitTimePurGoodBo,1);
    }

    /**
     * 修改秒杀活动
     * */
    @Transactional(rollbackFor = Throwable.class)
    public void update(UpdateLimitTimePurActiveBo bo,String userId) {
        ParamException.isTrue(!StringUtils.hasText(bo.getId()),"id为空");
        LimitTimePurActiveBo limitTimePurActiveBo = BeanConverUtils.convertBean(bo, LimitTimePurActiveBo.class);
        checkValue(limitTimePurActiveBo,userId);
        LimitTimePurActive limitTimePurActive = BeanConverUtils.convertBean(bo, LimitTimePurActive.class);
        limitTimePurActiveDao.updateByPrimaryKeySelective(limitTimePurActive);
        if (bo.getDownLimitTimePurGoodVo()!=null){
            for (LimitTimePurGoodBo vo:bo.getDownLimitTimePurGoodVo()) {
                LimitTimePurGood limit=new LimitTimePurGood();
                limit.setIsEffect(0);
                limit.setId(vo.getId());
                limitTimePurGoodDao.updateByPrimaryKeySelective(limit);
            }
            String repeat = limitTimePurGoodDao.checkItemRepeat();
            ParamException.isTrue(StringUtil.isNotEmpty(repeat),"商品重复上架活动:"+repeat);
            batchUpdateItemSign(bo.getDownLimitTimePurGoodVo(),0);
        }
        if (bo.getLimitTimePurGoodVo()!=null){
            for (LimitTimePurGoodBo vo:bo.getLimitTimePurGoodVo()) {
                LimitTimePurGood limitTimePurGood = BeanConverUtils.convertBean(vo, LimitTimePurGood.class);
                limitTimePurGood.setIsEffect(1);
                int i = limitTimePurGoodDao.updateGood(limitTimePurGood);
                if (i==0){
                    limitTimePurGoodDao.insert(limitTimePurGood);
                }
            }
            String repeat = limitTimePurGoodDao.checkItemRepeat();
            ParamException.isTrue(StringUtil.isNotEmpty(repeat),"商品重复上架活动:"+repeat);
            batchUpdateItemSign(bo.getLimitTimePurGoodVo(),1);
        }
    }

    /**
     * 删除活动商品
     * */
    @Transactional(rollbackFor = Throwable.class)
    public void deleteLimitGood(UpdateLimitTimePurActiveBo bo,String userId) {
        ParamException.isTrue(CollectionUtils.isEmpty(bo.getDownLimitTimePurGoodVo()),"数据为空");
        ShopVo shopVo = shopApi.judgeUserHasShop(userId,bo.getShopId()).getResult();
        ParamException.isNull(shopVo,"当前用户没有权限进行限时购操作");
        for (LimitTimePurGoodBo vo:bo.getDownLimitTimePurGoodVo()) {
            LimitTimePurGood limit=new LimitTimePurGood();
            limit.setIsEffect(0);
            limit.setDflag(1);
            limit.setId(vo.getId());
            limitTimePurGoodDao.updateByPrimaryKeySelective(limit);
        }
        batchUpdateItemSign(bo.getDownLimitTimePurGoodVo(),0);
    }



    /**
     * 删除限时购活动
     * */
    @Transactional(rollbackFor = Throwable.class)
    public void delete(String activeId) {
        ParamException.isTrue(!StringUtils.hasText(activeId));
        limitTimePurActiveDao.deleteById(activeId);
        QueryLimitTimePurGoodBo bo=new QueryLimitTimePurGoodBo();
        bo.setLimitActiveId(activeId);
        List<LimitTimePurGood> limitTimePurGoods = limitTimePurGoodDao.queryGood(bo);
        if(!CollectionUtils.isEmpty(limitTimePurGoods)){
            for (LimitTimePurGood limitTimePurGood:limitTimePurGoods) {
                limitTimePurGoodDao.deleteById(limitTimePurGood.getId());
            }
        }
        //更新标签
        batchUpdateItemSign(BeanConverUtils.convertBeanList(limitTimePurGoods,LimitTimePurGoodBo.class),0);
    }

    /**
     * 店铺商品删除/下架
     * */
    @Transactional(rollbackFor = Throwable.class)
    public void deleteGood(String itemId) {
        ParamException.isTrue(!StringUtils.hasText(itemId));
        QueryLimitTimePurGoodBo bo=new QueryLimitTimePurGoodBo();
        bo.setItemId(itemId);
        List<LimitTimePurGood> limitTimePurGoods = limitTimePurGoodDao.queryGood(bo);
        if(!CollectionUtils.isEmpty(limitTimePurGoods)){
            for (LimitTimePurGood limitTimePurGood:limitTimePurGoods) {
                limitTimePurGoodDao.deleteById(limitTimePurGood.getId());
            }
        }
    }

    /**
     * 店铺sku删除
     * */
    @Transactional(rollbackFor = Throwable.class)
    public void deleteSku(List<String> skuBarcodeList) {
        ParamException.isTrue(CollectionUtils.isEmpty(skuBarcodeList));
        for (String barcode:skuBarcodeList) {
            limitTimePurGoodDao.deleteByBarcode(barcode);
        }
    }

    /**
     * 主页限时购活动
     * @param bo
     * @return
     */
    public LimitTimePurActiveVo queryPageActive(QueryLimitTimePurActiveBo bo){
        ParamException.isBlank(bo.getShopId(),"门店id为空");
        bo.setIsEffect(1);
        List<LimitTimePurActiveVo> list = BeanConverUtils.convertBeanList(limitTimePurActiveDao.queryPageActive(bo),LimitTimePurActiveVo.class);
        getGoods(list);
        if (!CollectionUtils.isEmpty(list)){
            return list.get(0);
        }
        return null;
    }
    /**
     * 运营工具限时购活动
     * @param bo
     * @return
     */
    public List<LimitTimePurActiveVo> queryActive(QueryLimitTimePurActiveBo bo,String userId){
        ParamException.isBlank(bo.getShopId(),"门店id为空");
        ShopVo shopVo = shopApi.judgeUserHasShop(userId, bo.getShopId()).getResult();
        ParamException.isNull(shopVo,"当前用户没有权限操作");
        List<LimitTimePurActiveVo> list = BeanConverUtils.convertBeanList(limitTimePurActiveDao.queryActive(bo),LimitTimePurActiveVo.class);
        getGoods(list);
        return list;
    }

    private List<LimitTimePurActiveVo> getGoods(List<LimitTimePurActiveVo> list){
        if (!CollectionUtils.isEmpty(list)){
            for (LimitTimePurActiveVo vo:list) {
                QueryLimitTimePurGoodBo query=new QueryLimitTimePurGoodBo();
                query.setLimitActiveId(vo.getId());
                List<LimitTimePurGood> limitTimePurGoods = limitTimePurGoodDao.queryGood(query);
                List<LimitTimePurItemVo> sku = getSku(limitTimePurGoods);
                vo.setLimitTimePurItemVo(sku);
            }
        }
        return list;
    }

    public List<LimitTimePurItemVo> getGood(QueryLimitTimePurGoodBo bo){
        List<LimitTimePurGood> limitTimePurGoods = limitTimePurGoodDao.queryGood(bo);
        return getSku(limitTimePurGoods);
    }

    private List<LimitTimePurItemVo> getSku(List<LimitTimePurGood> limitTimePurGoods){
        if (CollectionUtils.isEmpty(limitTimePurGoods)){
            return null;
        }
        List<LimitTimePurItemVo> itemlist = new ArrayList<>();
        List<LimitTimePurGoodVo> list = new ArrayList<>();
        Map<String,List<LimitTimePurGoodVo>> map = new HashMap<>();
        for (LimitTimePurGood good:limitTimePurGoods) {
            list=map.get(good.getItemId());
            if (list==null){
                list = new ArrayList<>();
                map.put(good.getItemId(),list);
            }
            list.add(BeanConverUtils.convertBean(good,LimitTimePurGoodVo.class));
        }
        for (List<LimitTimePurGoodVo> value:map.values()) {
            if (!CollectionUtils.isEmpty(value)){
                LimitTimePurGoodVo cheap=value.stream().min(Comparator.comparing(LimitTimePurGoodVo::getLimitPrice)).orElse(null);
                LimitTimePurItemVo vo = BeanConverUtils.convertBean(cheap, LimitTimePurItemVo.class);
                vo.setLimitTimePurGoodVo(value);
                int salesCount = value.stream().mapToInt(LimitTimePurGoodVo::getSaleCount).sum();
                BigDecimal totalAmounts = value.stream().map(o -> o.getLimitPrice().multiply(new BigDecimal(o.getSaleCount()))).reduce(BigDecimal.ZERO, BigDecimal::add);
                vo.setSaleCount(salesCount);
                vo.setViewCount(value.get(0).getViewCount());
                vo.setTotalAmounts(totalAmounts);
                itemlist.add(vo);
            }
        }
        return itemlist;
    }



    /**
     * 更新订单信息
     * @return
     */
    public void updateOrder(ChangeStockBo changeStockBo){
        List<OrderSpuVo> list=new ArrayList<>();
        for (SkuSaleBo dto : changeStockBo.getSkuSaleList()) {
            OrderSpuVo vo = new OrderSpuVo();
            vo.setSkuCode(dto.getBarcode());
            vo.setSkuQty(dto.getSkuQty());
            list.add(vo);
        }
        if (changeStockBo.getType()==1){
            limitTimePurGoodDao.updateOrderCount(list);
        }
        if (changeStockBo.getType()==0){
            limitTimePurGoodDao.downOrderCount(list);
        }
    }


    /**
     * 更新浏览量
     * @return
     */
    @Async
    public void updateViewCount(String itemId,String activeId){
        ParamException.isBlank(activeId,"活动id为空");
        ParamException.isBlank(itemId,"商品id为空");
        limitTimePurGoodDao.updateViewCount(itemId,activeId);
    }


    /**
     * 更新标签
     * activeTag 1加标签 0去标签
     * @return
     */
    private void updateItemSign(String itemId,Integer activeTag){
        ParamException.isBlank(itemId,"商品id为空");
        itemDao.updateLimitTag(itemId,activeTag);
        if (activeTag==0){
            itemTagDao.deleteByItemIdAndCode(itemId, GoodsEnum.ItemTagEnum.LIMITED_TIME_PURCHASE.getCode());
        }else if (activeTag==1){
            ItemTag itemTag=new ItemTag();
            itemTag.setCode(GoodsEnum.ItemTagEnum.LIMITED_TIME_PURCHASE.getCode());
            itemTag.setItemId(itemId);
            itemTag.setName(GoodsEnum.ItemTagEnum.LIMITED_TIME_PURCHASE.getName());
            itemTagDao.insert(itemTag);
        }
    }

    /**
     * 批量更新标签
     * activeTag 1加标签 0去标签
     * @return
     */
    private void batchUpdateItemSign(List<LimitTimePurGoodBo> limitTimePurGoodBo,Integer activeTag){
        if (!CollectionUtils.isEmpty(limitTimePurGoodBo)){
            List<String> itemIds = limitTimePurGoodBo.stream().map(LimitTimePurGoodBo::getItemId).distinct().collect(Collectors.toList());
            itemDao.batchupdateLimitTag(itemIds,activeTag);
            if (activeTag==0){
                itemTagDao.deleteByItemIdsAndCode(itemIds, GoodsEnum.ItemTagEnum.LIMITED_TIME_PURCHASE.getCode());
            }else if (activeTag==1){
                List<ItemTag> list=new ArrayList<>();
                itemIds.stream().forEach(o->{
                    ItemTag itemTag=new ItemTag();
                    itemTag.setCode(GoodsEnum.ItemTagEnum.LIMITED_TIME_PURCHASE.getCode());
                    itemTag.setItemId(o);
                    itemTag.setName(GoodsEnum.ItemTagEnum.LIMITED_TIME_PURCHASE.getName());
                    list.add(itemTag);
                });
                itemTagDao.insertList(list);
            }
        }
    }


    /**
     * 商品详情(商品明细用)
     * @param bo
     * @return
     */
    public LimitTimePurGoodVo getLimitItemDetail(QueryLimitTimePurGoodBo bo){
        List<LimitTimePurGood> limitTimePurGoods = limitTimePurGoodDao.queryGood(bo);
        if (!CollectionUtils.isEmpty(limitTimePurGoods)){
            ((LimitTimePurActiveService) AopContext.currentProxy()).updateViewCount(limitTimePurGoods.get(0).getItemId(),limitTimePurGoods.get(0).getLimitActiveId());
            return BeanConverUtils.convertBean(limitTimePurGoods.get(0),LimitTimePurGoodVo.class);
        }
        return null;
    }

    /**
     * 限时购活动过期
     * @return
     */
    public void updateOverActive(){
        List<LimitTimePurActive> list = limitTimePurActiveDao.queryOverPurActive();
        if (!CollectionUtils.isEmpty(list)){
            for (LimitTimePurActive vo:list) {
                vo.setIsEffect(0);
                limitTimePurActiveDao.updateByPrimaryKeySelective(vo);
                LimitTimePurGood good=new LimitTimePurGood();
                good.setLimitActiveId(vo.getId());
                good.setIsEffect(0);
                limitTimePurGoodDao.updateGood(good);
                //更新标签
                QueryLimitTimePurGoodBo query=new QueryLimitTimePurGoodBo();
                query.setLimitActiveId(vo.getId());
                List<LimitTimePurGoodBo> goodBos = BeanConverUtils.convertBeanList(limitTimePurGoodDao.queryGood(query), LimitTimePurGoodBo.class);
                batchUpdateItemSign(goodBos,0);
            }
        }
    }

    public LimitTimeGoAndTimeVo limitTimeGo(String shopId) {
        LimitTimeGoAndTimeVo limitTimeGoAndTimeVo = new LimitTimeGoAndTimeVo();
        List<LimitTimePurActive> list = limitTimePurActiveDao.findProcessingActivity(shopId);
        if (!CollectionUtils.isEmpty(list)) {
            limitTimeGoAndTimeVo.setLimitTimeGo(BaseEnum.StatusEnum.ENABLE.getCode());
        }
        return limitTimeGoAndTimeVo;
    }
}

